﻿
namespace n_MusicPanel
{
using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using n_MusicFunction;
using n_MusicForm;
using n_Node;
using n_OS;
using n_SG;
using n_TNodeSet;

//*****************************************************
//简谱显示容器类
public class MusicPanel : Panel
{
	public bool ShowNetGrid;
	
	//版本
	public string Version;
	
	//歌曲名称
	public string Title;
	public string Mes;
	int TitleX;
	
	Pen RightLinePen;
	Pen RightLineBackPen;
	
	//摄像机位置
	public float CamMidX;
	public float CamMidY;
	//摄像机放缩比
	public float CamScale;
	
	//当前的鼠标移动位置
	PointF MousePoint;
	bool RightMouseDown;
	float lastX;
	float lastY;
	
	TNodeSet TNodeSet0;
	TNodeSet TNodeSet1;
	
	public static string Error;
	public static string Warning;
	
	Bitmap MesImage;
	bool ShowMes;
	
	const int MesHeight = 100;
	
	bool CtrlDown;
	
	Font f;
	
	//构造函数
	public MusicPanel( TNodeSet tn1, TNodeSet tn2, int Width, int Height ) : base()
	{
		this.BorderStyle = BorderStyle.None;
		SetStyle(ControlStyles.UserPaint |
		         ControlStyles.AllPaintingInWmPaint |
		         ControlStyles.OptimizedDoubleBuffer |
		         ControlStyles.ResizeRedraw |
		         ControlStyles.SupportsTransparentBackColor,true);
		
		//Cursor1 = new Cursor( OS.SystemRoot + "Resource" + OS.PATH_S + "myPointEdit.cur" );
		//Cursor2 = new Cursor( OS.SystemRoot + "Resource" + OS.PATH_S + "myPointMove.cur" );
		
		MesImage = new Bitmap( OS.SystemRoot + "Resource" + OS.PATH_S + "MusicBox" + OS.PATH_S + "mes.png" );
		
		f = new Font( "微软雅黑", 11 );
		
		TNodeSet0 = tn1;
		TNodeSet1 = tn2;
		
		Error = "";
		Warning = "";
		ShowMes = true;
		
		//this.Cursor = Cursor1;
		
		TitleX = Width/2;
		
		this.Width = Width;
		this.Height = Height;
		this.Location = new Point( 0, 0 );
		this.Dock = DockStyle.Fill;
		
		this.MouseMove += new MouseEventHandler( UserMouseMove );
		this.MouseUp += new MouseEventHandler( UserMouseUp );
		this.MouseDown += new MouseEventHandler( UserMouseDown );
		this.MouseWheel += new MouseEventHandler( UserMouseWheel );
		this.KeyDown += new KeyEventHandler( UserKeyDown );
		this.KeyUp += new KeyEventHandler( UserKeyUp );
		this.Click += delegate { this.Focus(); };
		
		ShowNetGrid = false;
		
		RightLinePen = new Pen( Color.Black, 3 );
		RightLineBackPen = new Pen( Color.SlateGray, 3 );
		
		CamMidX = Width/2;
		CamMidY = Height/2;
		CamScale = 1;
		
		RightMouseDown = false;
		lastX = 0;
		lastY = 0;
	}
	
	//重绘事件
	protected override void OnPaint(PaintEventArgs e)
	{
		Graphics g = e.Graphics;
		GraphicsState gs = g.Save();
		
		SG.SetObject( g );
		SG.g.Clear( Color.White );
		
		float RolX = Width/2;
		float RolY = Height/2;
		
		//摄像机按照中心位置进行旋转
		//SG.Rotate( RolX, RolY, CamAngle );
		//摄像机按照中心位置进行放缩
		SG.Scale( RolX, RolY, CamScale );
		//摄像机移动到指定点
		SG.Transfer( -(CamMidX - RolX), -(CamMidY - RolY) );
		
		//绘制标题
		SG.MString.DrawAtCenter( Title, Color.Black, 19, TitleX, 17 );
		
		//绘制信息
		SG.MString.DrawAtCenter( Mes, Color.Gray, 12, TitleX, 40 );
		
		//绘制:  1=C, 音量, 移调, 时值单位, 节拍和小节
		SG.MString.DrawAtLeft( "1=♪" + TNode.DoEqual, Color.Black, 11, 5, 30 );
		
		SG.MString.DrawAtRight( "主旋音量:" + TNodeSet0.Volume, Color.Gray, 10, TitleX*2 - 30, 15 );
		SG.MString.DrawAtRight( "伴奏音量:" + TNodeSet1.Volume, Color.Gray, 10, TitleX*2 - 30, 30 );
		SG.MString.DrawAtRight( "播放速度:" + TNode.TimeTick + "ms", Color.Gray, 10, TitleX*2 - 30, 45 );
		
		SG.MString.DrawAtCenter( TNode.PiN.ToString(), Color.Black, 11, 80, 20 );
		SG.MString.DrawAtLeft( "拍数(每小节)", Color.Gray, 11, 90, 20 );
		SG.MLine.Draw( Color.Black, 1, 73, 30, 87, 30 );
		SG.MString.DrawAtCenter( TNode.Fen.ToString(), Color.Black, 11, 80, 40 );
		SG.MString.DrawAtLeft( "分音符为一拍", Color.Gray, 11, 90, 40 );
		
		//绘制音符列表
		SG.MString.SetDefultFont( false );
		TNodeSet0.Draw();
		TNodeSet1.Draw();
		SG.MString.SetDefultFont( true );
		
		g.Restore( gs );
		if( ShowMes ) {
			
			/*
			int sx = (Width - MesImage.Width)/2;
			int sy = Height - MesImage.Height - 5;
			if( sx < 5 ) {
				sx = 5;
			}
			if( sy < 5 ) {
				sy = 5;
			}
			*/
			
			g.FillRectangle( Brushes.CornflowerBlue, 0, Height - MesHeight, Width, MesHeight );
			g.DrawString( "1. 通过修改 1=(?) 可以调节音乐播放的整体音高. 如果音调发沉, 可以适当增大数值. 默认1=60 (即1=C);", f, Brushes.WhiteSmoke, 10, Height - MesHeight + 10 );
			g.DrawString( "2. 通过设置最小时值单位可以调节音乐播放速度, 最小时值单位表示的是一个128分音符的时间;", f, Brushes.WhiteSmoke, 10, Height - MesHeight + 30 );
			g.DrawString( "3. 每个音节的时值不允许跨小节, 如果确实需要跨小节, 请拆分成两个音节, 并通过连音标志连接;", f, Brushes.WhiteSmoke, 10, Height - MesHeight + 50 );
			g.DrawString( "按住Ctrl键可通过鼠标滚轮调节界面放缩", f, Brushes.Yellow, 10, Height - MesHeight + 80 );
			
			//SG.MBitmap.Draw( MesImage, sx, sy );
		}
		//绘制出错信息
		if( Error != "" || Warning != "" ) {
			SG.MRectangle.Fill( Color.DarkOrange, 0, Height - 40, Width, 40 );
			SG.MString.DrawAtLeft( Error, Color.White, 11, 10, Height - 10 );
			SG.MString.DrawAtLeft( Warning, Color.White, 11, 10, Height - 30 );
		}
	}
	
	public PointF GetWorldPoint( float mouseX, float mouseY )
	{
		mouseX = mouseX - Width/2;
		mouseY = mouseY - Height/2;
		
		mouseX = mouseX/CamScale;
		mouseY = mouseY/CamScale;
		
		//double R = Math.Cos( -CamAngle * Math.PI/180 );
		//double I = Math.Sin( -CamAngle * Math.PI/180 );
		//double x = mouseX*R - mouseY*I;
		//double y = mouseX*I + mouseY*R;
		
		double x = mouseX;
		double y = mouseY;
		
		return new PointF( (float)(CamMidX + x), (float)(CamMidY + y) );
	}
	
	public PointF GetWorldPoint( float mouseX, float mouseY, int LastW, int LastH )
	{
		mouseX = mouseX - LastW/2;
		mouseY = mouseY - LastH/2;
		
		mouseX = mouseX/CamScale;
		mouseY = mouseY/CamScale;
		
		//double R = Math.Cos( -CamAngle * Math.PI/180 );
		//double I = Math.Sin( -CamAngle * Math.PI/180 );
		//double x = mouseX*R - mouseY*I;
		//double y = mouseX*I + mouseY*R;
		
		double x = mouseX;
		double y = mouseY;
		
		return new PointF( (float)(CamMidX + x), (float)(CamMidY + y) );
	}
	
	void UserKeyDown( object sender, KeyEventArgs e )
	{
		if( e.KeyCode == Keys.ControlKey ) {
			CtrlDown = true;
		}
	}
	
	void UserKeyUp( object sender, KeyEventArgs e )
	{
		if( e.KeyCode == Keys.ControlKey ) {
			CtrlDown = false;
		}
	}
	
	//鼠标滚轮事件
	void UserMouseWheel( object sender, MouseEventArgs e )
	{
		
		if( CtrlDown ) {
		
			PointF p = GetWorldPoint( e.X, e.Y );
			if( e.Delta > 0 ) {
				if( CamScale < 100 ) {
					CamScale *= 1.25f;
				}
			}
			else {
				if( CamScale > 0.05 ) {
					CamScale /= 1.25f;
				}
			}
			PointF p1 = GetWorldPoint( e.X, e.Y );
			CamMidX += p.X - p1.X;
			CamMidY += p.Y - p1.Y;
		}
		else {
			n_Main.Program.f.UpDown( e.Delta );
		}
		Invalidate();
	}
	
	//鼠标按下事件
	void UserMouseDown( object sender, MouseEventArgs e )
	{
		if( e.Button == MouseButtons.Left && !ShowMes ) {
			TNode t0 = TNodeSet0.MouseDown( MousePoint );
			TNode t1 = TNodeSet1.MouseDown( MousePoint );
			if( t1 != null ) {
				t0 = t1;
			}
			if( t0 == null ) {
				TNodeSet.SelectedTNode = null;
			}
			else if( t0 != TNodeSet.SelectedTNode ) {
				TNodeSet.SelectedTNode = t0;
			}
			else {
				//点击了同一个音符, 忽略
				//...
			}
			
			RightMouseDown = true;
			lastX = e.X;
			lastY = e.Y;
			
			ShowMes = false;
		}
		if( e.Button == MouseButtons.Right ) {
			//RightMouseDown = true;
			//lastX = e.X;
			//lastY = e.Y;
		}
		if( ShowMes && e.Button == MouseButtons.Left ) {
			ShowMes = false;
		}
		Invalidate();
	}
	
	//鼠标松开事件
	void UserMouseUp( object sender, MouseEventArgs e )
	{
		if( e.Button == MouseButtons.Left ) {
			TNodeSet0.MouseUp( MousePoint );
			TNodeSet1.MouseUp( MousePoint );
			RightMouseDown = false;
		}
		if( e.Button == MouseButtons.Right ) {
			//RightMouseDown = false;
		}
		Invalidate();
	}
	
	//鼠标移动事件
	void UserMouseMove( object sender, MouseEventArgs e )
	{
		if( e.Y > Height - MesHeight ) {
			ShowMes = false;
		}
		
		MousePoint = GetWorldPoint( e.X, e.Y );
		TNodeSet0.MouseMove( MousePoint );
		TNodeSet1.MouseMove( MousePoint );
		if( RightMouseDown ) {
			float ox = -(e.X - lastX) / CamScale;
			float oy = -(e.Y - lastY) / CamScale;
			
			//double R = Math.Cos( -CamAngle * Math.PI/180 );
			//double I = Math.Sin( -CamAngle * Math.PI/180 );
			//double dx = ox*R - oy*I;
			//double dy = ox*I + oy*R;
			
			double dx = ox;
			double dy = oy;
			
			CamMidX += (float)dx;
			CamMidY += (float)dy;
			lastX = e.X;
			lastY = e.Y;
		}
		if( n_Main.Program.f.timerPlay.Enabled ) {
			return;
		}
		Invalidate();
	}
}
}



